#-*- coding: UTF-8 -*-
from random import randint, choice
from cStringIO import StringIO

import Image, ImageDraw, ImageFont
import os

class Captcha(object):
   """
   网页验证码生成器
   """

   # 字母和数字
   LETTER_NUMBER_CHARS = ('0', '1', '2', '3', '4', '5', '6', '7',
'8', '9',
           'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
           'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
           'U', 'V', 'W', 'X', 'Y', 'Z',
           'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j',
           'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't',
           'u', 'v', 'w', 'x', 'y', 'z')

   # 仅数字
   NUMBER_CHARS = ('0', '1', '2', '3', '4', '5', '6', '7', '8', '9')

   # 仅字母
   LETTER_CHARS = ('A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
           'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
           'U', 'V', 'W', 'X', 'Y', 'Z',
           'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j',
           'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't',
           'u', 'v', 'w', 'x', 'y', 'z');

   DEFAULT_FONT_PATH = os.path.join(os.path.dirname(__file__),'Vera.ttf').replace('\\', '/')

   def __init__(self, char_type = LETTER_CHARS, code_length = 4, font_path = DEFAULT_FONT_PATH, font_size = 18):
       """
           初始化
           @param char_type: 字符集类型 LETTER_NUMBER_CHARS|NUMBER_CHARS|
LETTER_CHARS, 默认:LETTER_CHARS
           @param code_length: 验证码的位数, 默认:4
           @param font_path: truetype字体的路径, 默认: Vera
           @param font_size: truetype字体的大小, 默认: 18
       """

       self.char_type = char_type
       self.code_length = code_length
       self.width = 14 * self.code_length + 10
       self.height = 20;
       self.font_path = font_path
       self.font_size = font_size

   def fill(self, out):
       """
           填充到数据流中
           @param out: 输出流, 一般为file, StringIO等
       """

       # 在内存中初始化图片
       image = Image.new('RGB', (self.width, self.height),
(255,255,255))

       # 建立绘图引擎
       draw = ImageDraw.Draw(image)

       # 设定背景色
       draw.rectangle([(0,0),(self.width, self.height)],
self._get_rnd_color(100, 159))

       # 随机产生干扰线，使图象中的认证码不易被其它程序探测到
       self._fill_jam(draw)

       # 取随机产生的认证码(CODE_LEN位数字)
       code = self._fill_code(draw)

       # 画边框
       self._fill_box(draw)

       # 输出图象到流设备
       #image.save(out,"JPEG")
       image.save(out,"GIF")

       # 清除draw对象
       del draw

       # 返回生成的字符串
       return code

   def _fill_jam(self, draw):
       """
           随机产生干扰线，使图象中的认证码不易被其它程序探测到
       """
       line_count = self.code_length * 15;
       color = self._get_rnd_color(160, 199)
       while line_count > 0:
           line_count -= 1
           x = randint(0, self.width)
           y = randint(0, self.height)
           x1 = randint(0, 12)
           y1 = randint(0, 12)
           draw.line([(x, y), (x + x1, y + y1)], color)

   def _fill_code(self, draw):
       """
           根据code_length,从char_type中取得随机的字符, 组成列表
       """

        # 设置字体
       font = ImageFont.truetype(self.font_path, self.font_size)

       code = []
       for i in range(self.code_length):
           c = choice(self.char_type)
           code.append(c)
           color = self._get_rnd_color(200, 255)
           draw.text((14 * i + 6, 0), c, font=font, fill=color)
       return ''.join(code)

   def _get_rnd_color(self, fc, bc):
       """
           给定范围获得随机颜色
       """
       if fc > 255:
           fc = 255
       if bc > 255:
           bc = 255
       r = fc + randint(0, bc - fc)
       g = fc + randint(0, bc - fc)
       b = fc + randint(0, bc - fc)
       return (r, g, b)

   def _fill_box(self, draw):
       """
           画边框
       """
       draw.line([(0, 0), (self.width, 0)], fill=(0,0,0))
       draw.line([(self.width, 0), (self.width-1, self.height-1)],
fill=(0,0,0))
       draw.line([(self.width-1, self.height-1), (0, self.height-1)],
fill=(0,0,0))
       draw.line([(0, self.height-1), (0, 0)], fill=(0,0,0))

_default_captcha = None

def get_captcha():
   """
       取得默认的captcha
       @return: Captcha
   """
   global _default_captcha

   if _default_captcha:
       return _default_captcha
   else:
       _default_captcha = Captcha(Captcha.NUMBER_CHARS)
       return _default_captcha

def process_request():
   # 得到默认的captcha
   captcha = get_captcha()

   # 内存的输出流
   out = StringIO()

   # 生成
   code = captcha.fill(out)

   # 流索引贵0, 以便读取内容
   out.seek(0)

   return (code,out)
